<?php

namespace fakis\config\adapters;

use yii\base\Component;
use yii\db\Connection;
use yii\db\Query;
use yii\di\Instance;
use yii\helpers\Json;

/**
 * 数据库适配器
 *
 * @author Fakis <fakis738@qq.com>
 */
class DbAdapter extends Component implements AdapterInterface
{
    /**
     * 数据库连接
     * @var Connection
     */
    public $db = 'db';

    /**
     * 数据库表名
     * @var string
     */
    public $tableName = '{{%config}}';

    /**
     * 标识字段名
     * 一般不需要修改，如果修改，需要数据库字段一一对应
     * @var string
     */
    public $symbolField = 'symbol';

    /**
     * 配置数据字段名
     * 一般不需要修改，如果修改，需要数据库字段一一对应
     * @var string
     */
    public $dataField = 'data';

    /**
     * @inheritDoc
     */
    public function init()
    {
        parent::init();

        $this->db = Instance::ensure($this->db, Connection::class);
    }

    /**
     * 查询数据
     * @param string $symbol
     * @return array|null
     */
    public function query(string $symbol): ?array
    {
        $result = (new Query())->from($this->tableName)
            ->select([$this->dataField])
            ->where([$this->symbolField => $symbol])
            ->scalar($this->db);

        return !empty($result) ? Json::decode($result) : null;
    }

    /**
     * 保存配置数据
     * @param string $symbol
     * @param array $attributes
     * @return bool
     * @throws \yii\db\Exception
     */
    public function store(string $symbol, array $attributes): bool
    {
        $command = $this->db->createCommand();
        $columns = [$this->symbolField => $symbol, $this->dataField => $attributes];

        if ($this->query($symbol)) {
            $command->update($this->tableName, $columns, [$this->symbolField => $symbol]);
        } else {
            $command->insert($this->tableName, $columns);
        }

        return (bool)$command->execute();
    }

    /**
     * 清空配置数据
     * @param string $symbol
     * @return bool
     * @throws \yii\db\Exception
     */
    public function clear(string $symbol): bool
    {
        return (bool)$this->db->createCommand()->delete($this->tableName, [$this->symbolField => $symbol])->execute();
    }
}